//
//  HLNetWork.swift
//  SwiftPods
//
//  Created by hulinhu on 2018/1/16.
//  Copyright © 2018年 hulinhu. All rights reserved.
//

import Foundation
import Moya
import RxSwift
import RxCocoa
import Alamofire

// 网络请求全局设置
public func defaultAlamofireManager() -> Manager {
    
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let policies: [String: ServerTrustPolicy] = [
        "ap.grtstar.cn": .disableEvaluation
    ]
    let manager = Alamofire.SessionManager(configuration: configuration,serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies))
    manager.startRequestsImmediately = false
    return manager
}

private func endpointMapping<Target: TargetType>(target: Target) -> Endpoint<Target> {
    
    print("请求连接：\(target.baseURL)\(target.path) \n方法：\(target.method)\n参数：\(String(describing: target.headers)) ")
    
    return MoyaProvider.defaultEndpointMapping(for: target)
}

class HLNetWorkProvider<Target> where Target : Moya.TargetType {
    
    private let online: Observable<Bool>  // 网络监听
    private let provider: MoyaProvider<Target>

    // 重新 init 方法
    init(endpointClosure: @escaping MoyaProvider<Target>.EndpointClosure = MoyaProvider.defaultEndpointMapping,
         requestClosure: @escaping MoyaProvider<Target>.RequestClosure = Networking.endpointResolver(),
         stubClosure: @escaping MoyaProvider<Target>.StubClosure = MoyaProvider.neverStub,
         manager: Manager = MoyaProvider<Target>.defaultAlamofireManager(),
         plugins: [PluginType] = [],
         trackInflights: Bool = false,
         online: Observable<Bool> = connectedToInternetOrStubbing()) {
        
        self.online = online
        self.provider = MoyaProvider(endpointClosure: endpointMapping, requestClosure: requestClosure, stubClosure: stubClosure, manager: defaultAlamofireManager(), plugins: [HLNetRequestPlugin(),netWorkActivityPlugin], trackInflights: trackInflights)
    }
    
    // 当无网络时候进行 一次请求
    func request(_ token: Target) -> Observable<Moya.Response> {
        let actualRequest = provider.rx.request(token)
        return online
            .ignore(value: false)  // Wait until we're online
            .take(1)        // Take 1 to make sure we only invoke the API once.
            .flatMap { _ in // Turn the online state into a network request
                return actualRequest
        }
    }
    
}

//  请求超时
struct Networking {
    static func endpointResolver<T>() -> MoyaProvider<T>.RequestClosure where T: TargetType {
        return { (endpoint, closure) in
            if var request = try? endpoint.urlRequest() {
                request.httpShouldHandleCookies = false
                request.timeoutInterval = 15
                closure(.success(request))
            }
        }
    }
    static var plugins: [PluginType] {
        return [NetworkLoggerPlugin()]
    }
}



